home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / utilit~1 / initsnb.zoo / init / getty / getty.c next >
Encoding:
C/C++ Source or Header  |  1992-10-26  |  9.5 KB  |  462 lines

  1. /*
  2.  * getty.c - main code
  3.  * Part of getty(8) for MiNT by Dave Gymer
  4.  * Copyright (C) 1991 D P Gymer. All rights reserved.
  5.  * $Id: getty.c,v 0.1 1992/01/08 15:58:56 dpg Exp dpg $
  6.  * $Log: getty.c,v $
  7.  * Revision 0.2  1992/08/17  22:33:17  sru
  8.  * Added support for setting the baud rate.
  9.  *
  10.  * Revision 0.1  1992/01/08  15:58:56  dpg
  11.  * Added select(2) call (at least temporarily) so that lines on which this
  12.  * call works will not tie up CPU time.
  13.  * Added support for environmental changes. Still need to add the `ev'
  14.  * capability.
  15.  *
  16.  * Revision 0.0  1991/11/24  19:43:44  dpg
  17.  * First experimental version.
  18.  *
  19.  */
  20.  
  21. #include <ctype.h>
  22. #include <errno.h>
  23. #include <fcntl.h>
  24. #include <ioctl.h>
  25. #include <sgtty.h>
  26. #include <signal.h>
  27. #include <stat.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include <termcap.h>
  32. #include <time.h>
  33. #include <unistd.h>
  34.  
  35. #define GETTYTAB "/etc/gettytab"
  36. #ifndef LOGIN
  37. #define LOGIN "/usr/bin/login"
  38. #endif
  39.  
  40. extern int putenv(char *);
  41. extern char **environ;
  42.  
  43. #ifdef atarist
  44. int     __default_mode__ = 1;    /* All binary streams, please. */
  45. #endif
  46.  
  47. struct gettytab {
  48.     struct tchars gt_tchars;
  49.     struct ltchars gt_ltchars;
  50.     struct sgttyb gt_sgttyb;
  51.     char    prompt[32];
  52.     char    banner[80];
  53.     char    hostname[32];
  54.     char    login[FILENAME_MAX];
  55.     char    next[32];
  56. };
  57.  
  58. /* In case we get signalled, eg. alarm. */
  59. struct sgttyb save_sgttyb;
  60.  
  61. /*
  62.  * This isn't terribly efficient, but then it doesn't have to be, since
  63.  * getty is only here until someone logs on.
  64.  */
  65.  
  66. int
  67. my_putenv(char *string)
  68. {
  69.     if (!(string = strdup(string)))
  70.         perror("getty: malloc");
  71.     else
  72.         putenv(string);
  73. }
  74.  
  75. /*
  76.  * Take the current hostname and the hostname editing string and
  77.  * produce a new hostname.
  78.  */
  79.  
  80. void
  81. hostname_edit(char *hostname, char *edit)
  82. {
  83.     char    oldname[32],
  84.            *name;
  85.  
  86.     strcpy((name = oldname), hostname);
  87.     do {
  88.         switch (*edit) {
  89.         case '@':    /* Add a character. */
  90.             if (*name)
  91.                 *hostname++ = *name++;
  92.             break;
  93.         case '#':    /* Skip a character. */
  94.             if (*name)
  95.                 ++name;
  96.             break;
  97.         default:    /* Includes the null terminator. */
  98.             *hostname++ = *edit;
  99.         }
  100.     } while (*edit++);
  101. }
  102.  
  103. /*
  104.  * Deal with the entry, setting the table entries as required.
  105.  */
  106.  
  107. void
  108. deal_with_entry(char *entbuf, struct gettytab *buf)
  109. {
  110.     char    sbuf[128],
  111.         termvar[64],
  112.            *s = sbuf;
  113.     int     n;
  114.  
  115.     if (tgetstr("nx", &s))
  116.         strcpy(buf -> next, (s = sbuf));
  117.     else
  118.         *buf -> next = '\0';
  119.     if (tgetstr("hn", &s))
  120.         strcpy(buf -> hostname, (s = sbuf));
  121.     if (tgetstr("he", &s))
  122.         hostname_edit(buf -> hostname, (s = sbuf));
  123.     if (tgetstr("lm", &s))
  124.         strcpy(buf -> prompt, (s = sbuf));
  125.     if (tgetstr("lo", &s))
  126.         strcpy(buf -> login, (s = sbuf));
  127.     if (tgetstr("im", &s))
  128.         strcpy(buf -> banner, (s = sbuf));
  129.     if ((n = tgetnum("to")) != -1)
  130.         alarm(n);
  131.     if (tgetstr("tt", &s)) {
  132.         sprintf(termvar, "TERM=%s", (s = sbuf));
  133.         my_putenv(termvar);
  134.     }
  135.     if (tgetstr("sp", &s)) {
  136.         sscanf(sbuf, "%d", &n);
  137.  
  138.         switch(n)
  139.         {
  140.         case 50:
  141.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B50;
  142.             break;
  143.  
  144.         case 75:
  145.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B75;
  146.             break;
  147.  
  148.         case 110:
  149.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B110;
  150.             break;
  151.  
  152.         case 135:
  153.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B135;
  154.             break;
  155.  
  156.         case 150:
  157.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B150;
  158.             break;
  159.  
  160.         case 200:
  161.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B200;
  162.             break;
  163.  
  164.         case 300:
  165.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B300;
  166.             break;
  167.  
  168.         case 600:
  169.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B600;
  170.             break;
  171.  
  172.         case 1200:
  173.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B1200;
  174.             break;
  175.  
  176.         case 1800:
  177.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B1800;
  178.             break;
  179.  
  180.         case 2400:
  181.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B2400;
  182.             break;
  183.  
  184.         case 4800:
  185.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B4800;
  186.             break;
  187.  
  188.         case 9600:
  189.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B9600;
  190.             break;
  191.  
  192.         case 19200:
  193.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B19200;
  194.             break;
  195.  
  196.         case 38400:
  197.             buf->gt_sgttyb.sg_ispeed = buf->gt_sgttyb.sg_ospeed = B38400;
  198.             break;
  199.         }
  200.     }
  201.         
  202. }
  203.  
  204. /*
  205.  * Get a termcap entry from a named file.
  206.  */
  207.  
  208. int
  209. tgetent_other(char *entbuf, char *type, char *file)
  210. {
  211.     extern char **environ;
  212.     char  **oldenv = environ,
  213.             envbuf[128],
  214.            *tmpenv[] = {envbuf, 0},
  215.             retval;
  216.  
  217.     sprintf(envbuf, "TERMCAP=%s", file);
  218.     environ = tmpenv;
  219.     retval = tgetent(entbuf, type);
  220.     environ = oldenv;
  221.     return retval;
  222. }
  223.  
  224. /*
  225.  * Find the entry for a particular type and store it in buf.
  226.  * If no entry is found, use some defaults.
  227.  */
  228.  
  229. void
  230. get_getttytab(char *type, struct gettytab *buf)
  231. {
  232.     char    entbuf[2048];
  233.  
  234.     switch (tgetent_other(entbuf, type, GETTYTAB)) {
  235.     case -1:
  236.     case 0:
  237.         sprintf(entbuf, "getty: non-existant type `%s'\r\n",
  238.             type);
  239.         write(0, entbuf, strlen(entbuf));
  240.         break;
  241.     default:
  242.         deal_with_entry(entbuf, buf);
  243.     }
  244. }
  245.  
  246. /*
  247.  * Format a string.
  248.  * This consists mainly of substituting for %h and the like.
  249.  * BUGS
  250.  *    - doesn't check for the end of the string buffer
  251.  */
  252.  
  253. char *
  254. fmtstring(const char *s, struct gettytab *tab)
  255. {
  256.     static char buf[128];
  257.     char   *bp = buf;
  258.  
  259.     while (*s)
  260.         if (*s == '%') {
  261.             switch (*++s) {
  262.             case '\0':
  263.                 goto out;
  264.             case 'h':
  265.                 strcpy(bp, tab -> hostname);
  266.                 while (*bp)
  267.                     ++bp;
  268.                 break;
  269.             case 't':
  270.                 strcpy(bp, ttyname(0));
  271.                 while (*bp)
  272.                     ++bp;
  273.                 break;
  274.             default:
  275.                 *bp = *s;
  276.             }
  277.             ++s;
  278.         } else
  279.             *bp++ = *s++;
  280. out:
  281.     *bp = '\0';
  282.     return buf;
  283. }
  284.  
  285. /*
  286.  * Read the login name.
  287.  * If break is pressed (or what we think is probably break), we try to
  288.  * go to the next entry, by returning zero.
  289.  */
  290.  
  291. int
  292. read_name(char *name, struct gettytab *buf, int canselect)
  293. {
  294.     char   *s,
  295.             c;
  296.     long fds = 1;
  297.     struct sgttyb tmpsg = buf -> gt_sgttyb;
  298.     extern long select(int, long *, long *, long *, struct timeval *);
  299.  
  300.     tmpsg.sg_flags |= RAW;
  301.     tmpsg.sg_flags &= ~(ECHO | CRMOD);
  302.     stty(0, &tmpsg);
  303.  
  304.     s = fmtstring(buf -> prompt, buf);
  305.     write(0, s, strlen(s));
  306.  
  307.     s = name;
  308.  
  309.     if (canselect)
  310.         select(1, &fds, 0, 0, 0);
  311.     while (read(0, &c, 1) == 1 && c != '\n' && c != '\r') {
  312.         if (!c || c & 128 || c == (buf -> gt_tchars).t_brkc)
  313.             return 0;
  314.         else if (c == (buf -> gt_sgttyb).sg_erase) {
  315.             if (s > name) {
  316.                 --s;
  317.                 write(0, &(buf -> gt_sgttyb).sg_erase, 1);
  318.                 write(0, " ", 1);
  319.                 write(0, &(buf -> gt_sgttyb).sg_erase, 1);
  320.             }
  321.         } else {
  322.             write(0, &c, 1);
  323.             *s++ = c;
  324.         }
  325.     }
  326.  
  327.     /* Did we end with \n or \r? If the latter, we want EOL mapping. */
  328.     if (c == '\n')
  329.         (buf -> gt_sgttyb).sg_flags &= ~CRMOD;
  330.     else
  331.         (buf -> gt_sgttyb).sg_flags |= CRMOD;
  332.  
  333.     *s = '\0';
  334.     write(0, "\r\n", 2);
  335.  
  336.     /* Did the name contain any lowercase letters? Assume not. */
  337.     s = name;
  338.     (buf -> gt_sgttyb).sg_flags &= ~LCASE;
  339.     do
  340.         if (islower(*s)) {
  341.             (buf -> gt_sgttyb).sg_flags |= LCASE;
  342.             break;
  343.         }
  344.     while (*s++);
  345.  
  346.     return 1;
  347. }
  348.  
  349. void
  350. do_alarm(long sig)
  351. {
  352.     char *s = "Connection timed out.\r\n";
  353.  
  354.     ioctl(0, TIOCSETP, &save_sgttyb);
  355.     write(0, s, strlen(s));
  356.     exit(1);
  357. }
  358.  
  359. int
  360. main(int argc, char **argv)
  361. {
  362.     struct gettytab tab;
  363.     char   *type = 0,
  364.            *tty,
  365.             buf[256];
  366.     int     fd,
  367.         canselect,
  368.             banner_flag = 1;
  369.     struct stat info;
  370.     extern int gethostname(char *, int);
  371. /*    extern int execle(const char *, const char *,...);*/
  372.     extern char *ttyname(int);
  373.  
  374.     ioctl(0, TIOCGETP, &save_sgttyb);
  375.     signal(SIGALRM, do_alarm);
  376.  
  377.     /* Check for arguments. We ignore all but the last two. */
  378.     if (argc > 2) {        /* a tty was specified */
  379.         close(0);
  380.         fd = open((tty = argv[--argc]), O_RDWR);
  381.         if (fd) {
  382.             dup2(fd, 0);
  383.             close(fd);
  384.             fd = 0;
  385.         }
  386.     } else
  387.         tty = ttyname(fd = 0);
  388.  
  389.     if (argc > 1)        /* a type was specified */
  390.         type = argv[--argc];
  391.  
  392.     if (fd < -1 || fd > 2)
  393.         close(fd);
  394.  
  395. #ifdef atarist
  396.     dup2(fd, -1);        /* Controlling terminal. */
  397. #endif
  398.     dup2(fd, 1);
  399.     dup2(fd, 2);
  400.  
  401.     /* Set up some defaults for the terminal type. */
  402.     ioctl(0, TIOCGETP, &tab.gt_sgttyb);
  403.     ioctl(0, TIOCGETC, &tab.gt_tchars);
  404.     ioctl(0, TIOCGLTC, &tab.gt_ltchars);
  405.     strcpy(tab.prompt, "login: ");
  406.     strcpy(tab.banner, "%h running MiNT: line %t");
  407.     strcpy(tab.login, LOGIN);
  408.     *tab.next = '\0';
  409.     gethostname(tab.hostname, 32);
  410.  
  411.     /* Get any default entries in the table. */
  412.     get_getttytab("default", &tab);
  413.  
  414.     /* Fselect(2) does not yet work on BIOS devices except the console. */
  415.     /* Probably when this works right, we won't need select anyway!!! */
  416. #ifndef USE_SELECT
  417.     if (!strcmp("/dev/console", tty) ||
  418.         !fstat(0, &info) && info.st_mode & S_IFMT != S_IFCHR)
  419.         canselect = 1;
  420.     else
  421.         canselect = 0;
  422. #else
  423.     canselect = 1;
  424. #endif
  425.  
  426.     /* Set up terminal type and read name until happy. */
  427.     for (;;) {
  428.         if (type && *type) {    /* Type to look up? */
  429.             get_getttytab(type, &tab);
  430.             ioctl(0, TIOCSETP, &tab.gt_sgttyb);
  431.             ioctl(0, TIOCSETC, &tab.gt_tchars);
  432.             ioctl(0, TIOCSLTC, &tab.gt_ltchars);
  433.         }
  434.         if (banner_flag) {    /* Print the banner? */
  435.             char   *s;
  436.  
  437.             s = fmtstring(tab.banner, &tab);
  438.             write(0, s, strlen(s));
  439.             banner_flag = 0;
  440.         }
  441.         if (!read_name(buf, &tab, canselect)) {    /* Try next entry. */
  442.             if (tab.next)
  443.                 type = tab.next;
  444.             else
  445.                 type = 0;
  446.             banner_flag = 1;
  447.         } else if (*buf)/* Got a name. */
  448.             break;
  449.     }
  450.     ioctl(0, TIOCSETP, &tab.gt_sgttyb);    /* May have changed some. */
  451.  
  452.     /* Call login. If LOGIN is in use, preserve $TERM. */
  453.     if (strcmp(LOGIN, tab.login))
  454.         execle(tab.login, tab.login, buf, (char *) 0, environ);
  455.     else
  456.         execle(tab.login, tab.login, "-p", buf, (char *) 0, environ);
  457.     sprintf(buf, "getty: can't exec (%s) - %s\r\n", tab.login,
  458.         errno > 0 && errno <= sys_nerr ? strerror(errno) : "???");
  459.     write(0, buf, strlen(buf));
  460.     return 1;
  461. }
  462.